/**
 *	流程模块主Flow
 *	开发者：雨中磐石
 *	地址：www.rockoa.com
 *	日期：2023-07-19
 */

package com.framework.Flow;


import com.framerock.baselib.CDate;
import com.framerock.baselib.RockList;
import com.framerock.db.DBConn;
import com.framerock.db.DBLimit;
import com.framerock.server.Request;
import com.framerock.server.Response;
import com.framerock.baselib.Json;
import com.framerock.baselib.Patter;
import com.framerock.baselib.Rock;
import com.framerock.baselib.RockMsg;
import com.framework.ACore.Model;
import com.framework.ACore.ModuleFields;
import com.framework.Model.ModelUsera;
import java.util.ArrayList;
import java.util.Map;

/**
 * 流程模块主Flow
 * */
public class Flow {

    /**
     * 模块编号
     * */
    public String modenum = "";

    /**
     * 模块名称
     * */
    public String modename = "";

    /**
     * 读取类型
     * */
    public String gtype = "";

    /**
     * 条件编号
     * */
    public String atype = "";

    /**
     * 添加分组编号
     * */
    public String pnum = "";

    /**
     * 当前时间
     * */
    public String now   = "";

    /**
     * 模块信息
     * */
    public Map<String, String> moders;

    /**
     * 当前单据数据
     * */
    public Map<String, String> data;

    /**
     * 单据的数据
     * */
    public Map<String, String> billrs = null;

    /**
     * 单位模块信息
     * */
    public Map<String, String> unitrs = null;

    /**
     * 请求Request
     * */
    public Request mRequest = null;

    /**
     * 操作数据库默的
     * */
    public DBConn nDb;

    /**
     * 流程一些回调的方法
     * */
    public FlowListener mFlowListener;

    /**
     * 操作对应主表的Model
     * */
    public Model mModel;

    /**
     * 分页使用
     * */
    public DBLimit mDBLimit;

    /**
     * 扩展基本方法
     * */
    public FlowBase mFlowBase;

    /**
     * 是否有流程
     * */
    public int isflow   = 0;


    /**
     * 单位模块下的ID
     * */
    public String funitid  = "0";

    /**
     * 对应主表
     * */
    public String table = "",

    /**
     * 模块id
     * */
                 modeid = "0",

    /**
     * 模块相应条件
     * */
                 mwhere = "",
    /**
     * 错误信息
     * */
                 errstr = "",
    /**
     * 主单据ID
     * */
                    mid = "0";

    /**
     * 单位ID
     * */
    public String COMPANYID = "0";

    /**
     * 是否单位模块
     * */
    public Boolean UnitModeBo = false;

    /**
     * 用户Model
     */
    public ModelUsera modelUsera;

    public Flow(DBConn dbs) {
        this.nDb    = dbs;
        modelUsera  = ModelUsera.get(dbs);
    }

    /**
     * 调用时这个必须要设置
     * */
    public void setRequest(Request req) {
        this.mRequest   = req;
        this.COMPANYID  = req.COMPANYID;
    }

    /**
     * 设置错误返回空字符串
     */
    public String setError(String msg)
    {
        this.errstr = msg;
        this.mRequest.setError(Response.returnError(msg), false);
        return "";
    }

    /**
     * 设置错误返回null
     */
    public Map<String, String> setErrors(String msg)
    {
        this.errstr = msg;
        this.mRequest.setError(Response.returnError(msg), false);
        return null;
    }
    public Boolean isError()
    {
        return this.mRequest.isError();
    }
    public String getError()
    {
        return this.errstr;
    }

    /*
     * 初始化流程信息
     * */
    public void initFlow(String num, Boolean inbo)
    {
        this.modenum        = num;
        this.mDBLimit       = new DBLimit(this.nDb, mRequest);
        this.mFlowListener  = FlowListener.get(this, num);

        this.pnum       = mRequest.get("pnum");
        this.atype      = mRequest.get("atype");
        this.gtype      = mRequest.get("gtype");
        this.mFlowListener.oninitFlow();
        this.mFlowBase  = new FlowBase(this);

        if(!inbo)return;//不加载信息流程
        this.moders     = Model.get(this.nDb, "flowset").getOne("`num`='" + num + "'");
        if (this.moders == null) {
            this.setError("mode(" + num + ")not found");
            return;
        }
        if (Rock.getMapString(this.moders, "status").equals("0")) {
            this.setError("mode(" + num + ")stop using");
            return;
        }
        this.modename   = moders.get("name");
        this.table      = moders.get("table");
        this.modeid     = moders.get("id");
        this.now        = CDate.now();
        this.moders.put("isflow", "0");
        this.mModel     = Model.get(this.nDb, this.table, mRequest);
    }

    /**
     * 初始化单位模块信息
     * */
    public void initFunit(String fuid)
    {
        this.UnitModeBo = false;
        this.funitid    = "0";
        this.isflow     = 0;
        if(Rock.isEmpt(fuid) || fuid.equals("0") || !Patter.isnumber(fuid))return;
        Map<String, String> unrs = Model.get(this.nDb, "flowunit").getOne("`id`="+fuid+" AND `modeid`="+this.modeid+"");
        if(unrs == null){
            this.setError("modeunit(" + fuid + ")not found");
            return;
        }
        if (Rock.getMapint(unrs, "status")==0) {
            this.setError("modeunit(" + fuid + ")stop using");
            return;
        }
        this.funitid    = fuid;
        this.isflow     = Rock.getMapint(unrs, "isflow");
        this.unitrs     = unrs;
        this.UnitModeBo = true;
        this.moders.put("isflow", unrs.get("isflow"));
    }

    /**
     * 加载单据数据
     * */
    public void initData(String mid)
    {
        if(isError())return;
        if(Rock.isEmpt(mid) || mid.equals("0"))return;
        this.mid     = mid;
        int lx       = mFlowListener.onCompanymode();
        String where = "`id`="+mid+"",owhere;
        owhere       = this.cidWhere(0);
        if(!Rock.isEmpt(owhere))where+=" AND "+owhere+"";
        owhere      = Rock.getMapString(moders, "where");
        if(!Rock.isEmpt(owhere))where+=" AND "+owhere+"";

        Map<String,String> da = mModel.getOne(where);
        if(da==null){
            this.setError("单据记录不存在了");
            return;
        }
        this.mwhere = "`table`='"+this.table+"' AND `mid`="+mid+"";
        this.data   = da;
        if(this.isflow >0 && this.UnitModeBo)mFlowBase.Bill().info();
    }

    /**
     * 初始化基础的Flow模型
     * @param dbs 数据库
     * @param num 模块编号
     * @return Flow
     */
    public static Flow get(DBConn dbs, String num, Request req)
    {
        Flow obj = new Flow(dbs);
        obj.setRequest(req);
        obj.initFlow(num, true);
        return obj;
    }

    /**
     * 初始化基础的Flow模型
     * @param dbs 数据库
     * @param num 模块编号
     * @return Flow
     */
    public static Flow gets(DBConn dbs, String num, Request req)
    {
        Flow obj = new Flow(dbs);
        obj.setRequest(req);
        obj.initFlow(num, false);
        return obj;
    }

    public Flow lets(String num)
    {
        return Flow.gets(this.nDb, num, this.mRequest);
    }

    public Flow let(String num)
    {
        return Flow.get(this.nDb, num, this.mRequest);
    }

    /**
     * 是否单位模式模块
     * */
    public Boolean isCompanymode()
    {
        Boolean bo = false;
        int isxt = Rock.getMapint(this.moders, "isxt");
        if(isxt==2)bo = true;
        int mode = mFlowListener.onCompanymode();
        if(mode ==2)bo = true;
        return bo;
    }

    /**
     * 创建一个Model的数据模型
     * */
    public Model getModel(String tab)
    {
        Model obj = Model.get(this.nDb, tab);
        obj.setRequest(mRequest);
        return obj;
    }

    /**
     * 记录所有字段
     * */
    public ArrayList<Map<String, String>> allFieldsArr = null;

    /**
     * 获取字段(后续使用缓存)
     * @param lx 0默认，1详情，2列表
     * */
    public ArrayList<Map<String, String>> getFieldsArr(int lx)
    {
        if(allFieldsArr != null)return allFieldsArr;
        ArrayList<Map<String, String>> farr = Model.get(this.nDb, "flowelement").getAll("`modeid`="+this.modeid+"", "*", "`sort`");
        farr = this.mFlowListener.onFieldsArr(farr);
        if(isflow > 0 && farr != null){
            Map<String, String> da,rs; int xu = -1;
            for(int i=0; i<farr.size();i++){
                rs = farr.get(i);
                if(rs.get("fields").equals("status")){ xu = i;break;}
            }
            da = ModuleFields.get().setName("流程状态").setData("flowstatus").setFields("status").setIszs(1).setFieldstype("select").setIsss(1).setIspx(1).setIslb(1).getDefMap();
            if(xu>-1){ farr.set(xu, da); }else { farr.add(da);}
        }
        allFieldsArr = farr;
        return farr;
    }

    /**
     * 获取字段的默认值
     * */
    public ArrayList<Map<String, String>> devFieldsarr(ArrayList<Map<String, String>> rows)
    {
        return new FlowInput(this).devFieldsarr(rows);
    }


    /**
     * 获取数据
     * */
    public ArrayList<Map<String, String>> getFlowData()
    {
        return mFlowBase.List().getFlowData();
    }
    public ArrayList<Map<String, String>> replaceRowsList(ArrayList<Map<String, String>> rows)
    {
        return mFlowBase.List().replaceRowsList(rows);
    }
    public String getSubdata(String zdid)
    {
        return mFlowBase.List().getSubdata(zdid);
    }

    /**
     * 根据模块条件获取列表数据
     * @param num 条件编号
     * @param fields 字段
     * @param limit 记录数
     * @param isreplace 是否列表页数据替换
     * */
    public ArrayList<Map<String, String>> getListData(String num, String fields, int limit, Boolean isreplace)
    {
        return mFlowBase.List().getListData(num, fields, limit, isreplace);
    }

    /**
     * 控制器调用的
     * */
    public String action(String act, String params)
    {
        return mFlowListener.onAction(act, params);
    }

    /**
     * 获取数据源
     * */
    public String getStore(String zdid)
    {
        return mFlowBase.Store().getStore(zdid);
    }
    public String getallStore(int lx)
    {
        return mFlowBase.Store().getallStore(lx);
    }

    /**
     * 读取自定义数据源
     * */
    public ArrayList<Map<String, String>> Store(String action, String params)
    {
        ArrayList<Map<String, String>> rows = mFlowListener.onStore(action, params);
        if(rows==null && action.equals("flowstatus"))rows = mFlowBase.Course().statusStore();
        return rows;
    }

    /**
     * 单位模块的条件
     * @param lx 0初始单据 ,2列表页，1唯一处理
     * */
    public String cidWhere(int lx)
    {
        String str  = "";
        int mode      = mFlowListener.onCompanymode();
        if(mode == 2)str = "`cid`="+this.COMPANYID+"";
        if((mRequest.USERTYPE==0 && this.isCompanymode()) || mRequest.COMPANYBOOL) {
            str = "`cid`="+this.COMPANYID+"";
        }
        if(mode==1 && mRequest.USERTYPE==0){
            if(lx==2){
                this.setError("无权限查看("+this.modename+")的列表数据");
                str = "1=2";//无权限查看
            }
        }
        if(mode==3)str = "";
        return str;
    }
    
    /**
     * 获取字段上值
     * */
    public String getFieldsval(String fields)
    {
    	if(this.data == null)return "";
    	return Rock.getMapString(this.data, fields);
    }

    /**
     * 获取单据下的值
     * */
    public String getBillval(String fields)
    {
        if(this.billrs == null)return "";
        return Rock.getMapString(this.billrs, fields);
    }


    /**
     * 获取编辑的数据
     * */
    public Map<String,String> getEditdata()
    {
        if(this.mid.equals("0"))return null;
        Map<String,String> da = data;
        //判断是否有编辑权限
        if(!this.isView())return this.setErrors("编辑时:无查看模块("+this.modename+")详情的权限");
        if(!this.isEdit())return this.setErrors("无编辑权限");
        da  = mFlowListener.onEditdatars(da);
        return da;
    }

    /**
     * 保存单据
     * */
    public String saveData(String mid)
    {
        return mFlowBase.Input().saveData(mid);
    }

    /**
     * 获取操作菜单
     * */
    public String getOptmenu()
    {
        ArrayList<Map<String, String>> data = mFlowBase.Xiang().getOptmenu();
        return Json.getListString(data, "lx,menuid,type,isup,issm");
    }
    public String optmenuRun(String menuid, String lx)
    {
        return mFlowBase.Xiang().optmenuRun(menuid, lx);
    }


    /**
     * 获取详情页数据
     * */
    public Map<String,String> getXiangdata()
    {
        if(!this.isView())return this.setErrors("无查看模块("+this.modename+")详情的权限");
    	return mFlowBase.Xiang().getXiangdata();
    }

    /**
     * 获取要展示的文件信息
     * @param ly 0详情页,1编辑,2列表
     * */
    public ArrayList<Map<String, String>> getFiledata(int ly)
    {
        String fids = "";
        if(ly==0)fids = mFlowBase.Xiang().getAllFileids();
        if(ly==1)fids = mFlowBase.Input().getAllFileids();
        if(ly==2)fids = mFlowBase.List().getAllFileids();

        ArrayList<Map<String, String>> rows = null;
        if(!Rock.isEmpt(fids)){
            rows = Model.get(this.nDb, "file").getAll("`fileid` in("+fids+")", "fileext,filename,filenum,filesizecn,thumbpath,fileid", "");
        }
        return rows;
    }


    public Boolean isView(){ return mFlowBase.Auth().isView(); }
    public Boolean isDelete(){ return mFlowBase.Auth().isDelete(); }
    public Boolean isEdit(){ return mFlowBase.Auth().isEdit(); }
    public Boolean isAdd(){ return mFlowBase.Auth().isAdd(); }
    public Boolean isDaochu(){ return mFlowBase.Auth().isDaochu(); }

    /**
     * 是否可导入
     * */
    public Boolean isDaoru(){ return mFlowBase.Auth().isDaoru(); }

    /**
     * 是否开启单据提醒设置
     * */
    public Boolean isRemind()
    {
        Boolean bo = mFlowListener.onRemind();
        if(bo != null)return bo;
        return isCompanymode();
    }

    /**
     * 单据提醒设置的
     * @return 返回一些信息
     * */
    public Map<String, String> remindInfo() { return mFlowListener.onRemindInfo(); }

    /**
     * 单据提醒运行时
     * */
    public Map<String, String> remindRuning() { return mFlowListener.onRemindRuning(); }


    /**
     * 删除单据
     * */
    public void delete()
    {
        mFlowBase.Xiang().delete(true);
    }


    public void addOption(String pnum, String num, String downcont[])
    {
        mFlowBase.Unit().addOption(pnum, num, downcont);
    }

    /**
     * 更新单位模块信息，第一次新增才更新
     * @param da 更新Map信息
     * @param unid 模块模块id
     * @param url 更新地址，默认新增是url是空的，或者
     * */
    public void updateUnit(Map<String, String> da, String unid, String url)
    {
        mFlowBase.Unit().updateUnit(da, unid, url);
    }

    /**
     * 验证是否为单位模块管理员
     * @param aid 单位人员id
     * */
    public Boolean isManage(String aid)
    {
        return mFlowBase.Unit().isManage(aid);
    }

    /**
     * 验证是否为单位模块管理员
     * */
    public Boolean isManage() { return isManage(mRequest.USEAID); }


    /**
     * 获取选择卡
     * */
    public ArrayList<Map<String, String>> getAtypeArr()
    {
        return mFlowBase.Where().getAtypeArr(this.pnum);
    }

    /**
     * 通过编号获取条件
     * @param num 条件编号
     * @param qom 主表别名如a.
     * */
    public String getFlowwhere(String num, String qom)
    {
        return mFlowBase.Where().getFlowwhere(num, qom);
    }

    /**
     * 通过编号获取条件
     * @param num 条件编号
     * */
    public String getFlowwhere(String num){return getFlowwhere(num, "");}

    /**
     * 条件的解析
     * @param str base64的字符串条件
     * */
    public String getFlowwheres(String str)
    {
        return mFlowBase.Where().getFlowwheres(str, "");
    }

    /**
     * 读取条件权限
     * */
    public Boolean whereAuth(int wtype)
    {
        return mFlowBase.Where().whereAuth(wtype);
    }

    /**
     * 默认值替换
     * */
    public String defaultValue(String str)
    {
        return mFlowBase.Where().defaultValue(str);
    }

    /**
     * 添加条件
     * */
    public void addLog(String name, String sm, String params[])
    {
        mFlowBase.Log().addLog(name, sm, params);
    }

    /**
     * 获取操作记录
     * */
    public ArrayList<Map<String, String>> getLog()
    {
        return mFlowBase.Log().getLog();
    }

    /**
     * 操作记录统计
     * */
    public int getLogcount()
    {
        return this.mFlowBase.Log().getLogcount();
    }

    /**
     * 获取排序的
     * */
    public String getOrderstr()
    {
        String sort  = mFlowListener.onDefaultOrder();
        String sort1 = Rock.getMapString(moders, "sortdir");
        if(!Rock.isEmpt(sort1))sort = sort1;
        return sort;
    }

    /**
     * 添加系统模块时
     * */
    public void flowUnitadd()
    {
        mFlowBase.Unit().flowUnitadd();
        mFlowListener.onFlowunitadd();
    }

    /**
     * 触发单据通知
     * @param act 触发类型
     * */
    public void sendTodo(String act)
    {
        mFlowBase.Todo().sendTodo(act);
    }

    /**
     * 给对应人发通知
     * @param receid 接收人id，单位人员id
     * @param title 通知标题
     * @param mess 通知内容
     * */
    public void addTodo(String receid, String title, String mess)
    {
        mFlowBase.Todo().addTodo(receid, title, mess);
    }

    /**
     * 发送流程通知
     * @param type 类型，next
     * @param receid 接收人id，单位人员id
     * @param title 标题
     * @param mess 消息内容
     * */
    public void flowTodo(String type, String receid, String title, String mess)
    {
        mFlowBase.Todo().flowTodo(type, receid, title, mess);
    }

    /**
     * 发送流程通知
     * @param type 类型，next
     * @param receid 接收人id，单位人员id
     * */
    public void flowTodo(String type, String receid)
    {
        flowTodo(type, receid, "", "");
    }

    /**
     * 是否自己的单据
     * */
    public Boolean isMydj()
    {
        String aid = Rock.getMapString(this.data, "aid");
        if(mRequest.USERABOOL && aid.equals(mRequest.USEAID))return true;
        return false;
    }


    /**
     * 获取子表数据
     * */
    public String getSubdataAll()
    {
        return mFlowBase.List().getSubdataAll();
    }

    /**
     * 首页显示数据
     * @param pnum 分组编号
     * */
    public String homeData(String pnum)
    {
        return mFlowBase.List().homeData(pnum);
    }

    /**
     * 子表信息
     * */
    public Map<String, String> subdataInfo(String info)
    {
        if(Rock.isEmpt(info))return null;
        Map<String, String> da = Rock.getMap();
        String arr[] = info.split(",");
        String num,fid="mid",where="";
        num = arr[0];if(arr.length>1)fid = arr[1];
        da.put("num", num);da.put("fid", fid);da.put("where", where);
        return da;
    }

    /**
     * receid的条件组合条件
     * @param ars 单位用户信息
     * @param fid 字段
     * @param orwhere 其他or的条件
     * */
    public String receidWhere(Map<String, String> ars, String fid, String orwhere)
    {
        return mFlowBase.Where().receidWhere(ars, fid, false, orwhere);
    }

    /**
     * 角标读取
     * @param pnum 条件分组编号
     * */
    public int getStotal(String pnum)
    {
       return mFlowListener.ongetStotal(pnum);
    }

    /**
     * 双击单元格保存
     * */
    public RockMsg SaveCelledit()
    {
        return mFlowBase.List().SaveCelledit();
    }

    /**
     * 提交到流程里面
     * */
    public void submitFlow()
    {
        mFlowBase.Bill().submitFlow();
    }

    /**
     * 获取流程步骤信息
     * */
    public RockList getFlowCourse()
    {
        return mFlowBase.Course().getFlowCourse();
    }

    /**
     * 获取已审批流程信息
     * */
    public ArrayList<Map<String, String>> getCourseLog()
    {
        return mFlowBase.Log().getCourseLog();
    }

    /**
     * 审批
     * @param zt 审批状态1,2,3
     * @param sm 审批说明
     * */
    public RockMsg check(int zt, String sm)
    {
        return mFlowBase.Course().check(zt, sm);
    }

    /**
     * 获取单据的状态
     * */
    public int billStatus()
    {
        int zt = Rock.getMapint(data, "status");
        return zt;
    }

    /**
     * 当前流程的状态
     * */
    public Map<String, String> nowStatus()
    {
        return mFlowBase.Course().nowStatus(billStatus());
    }
}